package com.fzy.core.system.service;

import ge.core.system.entity.Entity;
import ge.core.system.entity.Property;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.naming.NamingException;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jndi.JndiObjectFactoryBean;

import com.fzy.core.BaseService;
import com.fzy.core.entity.Page;
import com.fzy.core.system.entity.EntityWrapper;
import com.fzy.core.system.entity.PropertyWrapper;
import com.fzy.core.utils.BuilderUtils;
import com.fzy.core.utils.NumberUtils;
import com.fzy.core.utils.StringUtils;

public abstract class AbstractDbService extends BaseService {
	public AbstractDbService() {
		
	}
	
	public AbstractDbService(String jndiName) {
		JndiObjectFactoryBean jndi = new JndiObjectFactoryBean();
		jndi.setJndiName(jndiName);
		try {
			jndi.afterPropertiesSet();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}
		DataSource ds = (DataSource)jndi.getObject();
		jdbcTemplate = new JdbcTemplate(ds);
	}

	public AbstractDbService(String driverClassName, String url, String username, String password) {
		DataSource ds = new DriverManagerDataSource(driverClassName, url, username, password);
		jdbcTemplate = new JdbcTemplate(ds);
	}
	
	public abstract Page getEntitiesFromTables(EntityQuery entityQuery, Page page);
	public abstract Entity getEntityByTableName(String tableName);
	public abstract List getPropertiesByTableName(String tableName);
	
	public int saveEntityData(EntityWrapper entityWrapper, Map entityData,
			boolean isCreated) {
		int count = 0;
		List params = new ArrayList();
		String sql = "";
		if (isCreated) {
			sql = "insert into " + entityWrapper.getData().getTableName() + "(";
			for (Iterator iterator = entityWrapper.getProperties().iterator(); iterator
					.hasNext();) {
				PropertyWrapper property = (PropertyWrapper) iterator.next();
				Object value = entityData.get(property.getData().getNameText());
				if (value != null) {
					Object propertyValue = BuilderUtils.params2javaType(value,
							property.getJavaType());
					if (propertyValue != null) {
						if (count != 0)
							sql = sql + ", ";
						sql = sql + property.getColumnName();
						params.add(propertyValue);
						count++;
					}
				}
			}
			sql = sql + ") values (";
			for (int i = 0; i < count; i++) {
				if (i != 0)
					sql = sql + ", ";
				sql = sql + "?";
			}
			sql = sql + ")";
		} else if (entityWrapper.getHasKey()) {
			sql = "update " + entityWrapper.getData().getTableName() + " set ";
			for (Iterator iterator = entityWrapper.getProperties().iterator(); iterator
					.hasNext();) {
				PropertyWrapper property = (PropertyWrapper) iterator.next();
				Object value = entityData.get(property.getData().getNameText());
				if (value != null && !property.getIsKey()) {
					Object propertyValue = BuilderUtils.params2javaType(value,
							property.getJavaType());
					if (propertyValue != null) {
						if (count != 0)
							sql = sql + ", ";
						sql = sql + property.getColumnName() + " = ? ";
						params.add(propertyValue);
						count++;
					}
				}
			}
			sql += "where 1=1 ";
			for (Iterator iterator = entityWrapper.getKeyProperties()
					.iterator(); iterator.hasNext();) {
				PropertyWrapper property = (PropertyWrapper) iterator.next();
				Object value = entityData.get(property.getData().getNameText());
				Object propertyValue = BuilderUtils.params2javaType(value,
						property.getJavaType());
				if (count != 0)
					sql = sql + "and ";
				sql = sql + property.getColumnName() + " = ? ";
				params.add(propertyValue);
				count++;
			}
		}
		return updateSql(sql, params);
	}

	public Map getEntityDataByKey(EntityWrapper entityWrapper,
			HttpServletRequest request) {
		Map result = null;
		if (!entityWrapper.getHasKey())
			return result;
		String sql = "select * from " + entityWrapper.getData().getTableName()
				+ " where 1=1";
		List params = new LinkedList();
		boolean hasKeyParam = false;
		for (Iterator iterator = entityWrapper.getKeyProperties().iterator(); iterator
				.hasNext();) {
			PropertyWrapper p = (PropertyWrapper) iterator.next();
			String keyName = "m." + p.getData().getNameText();
			Object keyValue = request.getParameter(keyName);
			if (PropertyWrapper.JAVA_LONG.equals(p.getJavaType()))
				keyValue = NumberUtils.createLongSafely((String) keyValue);
			if(keyValue != null)
				hasKeyParam = true;
			sql += getConditionSql(keyValue, p.getColumnName() + " =", params);
		}
		if(!hasKeyParam) return result;

		return queryForMap(sql, params.toArray());
	}

	public Page getEntityDataList(Map parameters, EntityWrapper entityWrapper,
			Page page) {
		String sql = "select * from " + entityWrapper.getData().getTableName()
				+ " where 1=1";
		List params = new LinkedList();
		return queryPage(sql, params.toArray(), page);
	}

	public List getEntityDataList(Map parameters, EntityWrapper entityWrapper) {
		String sql = "select * from " + entityWrapper.getData().getTableName()
				+ " where 1=1";
		List params = new LinkedList();
		return queryForList(sql, params.toArray());
	}
	
	protected String getNameShow(String tableName, String comment) {
		String nameShow = tableName;
		if (!StringUtils.isBlank(comment)) {
			int firstParentheses = comment.indexOf("(");
			if (firstParentheses > -1) {
				comment = comment.substring(0, firstParentheses);
			}
			nameShow = comment;
		}
		if (StringUtils.isBlank(nameShow)) {
			nameShow = tableName;
		}
		return nameShow;
	}
	
	protected void handleCommentOfProperty(Property property, String comment){
		List flags = analysisComment(comment);
		// analysis content like "sequence:s_t_dict_type"
		for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
			String x = (String) iterator.next();
			if(x.indexOf(":") > -1){
				String[] y = x.split(":");
				if(y != null && y.length == 2){
					String type = StringUtils.trimToEmpty(y[0]).toLowerCase();
					String value = StringUtils.trimToEmpty(y[1]);
					if("sequence".equals(type)){
						property.setSequenceName(value.toLowerCase());
					}
					if("dict".equals(type)){
						property.setDictType(value);
					}
					if("format".equals(type)){
						property.setDateFormat(value);
					}
					if("default".equals(type)){
						property.setDefaultValue(value);
					}
					if("deleted".equals(type)){
						property.setIsWork("0");
					}
					if("reference".equals(type)){
						String[] z = value.toLowerCase().split(".");
						if(z != null && z.length == 2){
							property.setRefTable(z[0]);
							property.setRefColumn(z[1]);
						}
					}
				}
			}
		}
	}
	
	protected void handleCommentOfEntity(Entity entity, String comment){
		List flags = analysisComment(comment);
		// analysis content like "sequence:s_t_dict_type"
		for (Iterator iterator = flags.iterator(); iterator.hasNext();) {
			String x = (String) iterator.next();
			if(x.indexOf(":") > -1){
				String[] y = x.split(":");
				if(y != null && y.length == 2){
					String type = StringUtils.trimToEmpty(y[0]).toLowerCase();
//					String value = StringUtils.trimToEmpty(y[1]);
					if("deleted".equals(type)){
						entity.setIsWork("0");
					}
				}
			}
		}
	}
	
	protected List analysisComment(String comment){
		List flags = new LinkedList();
		
		// cut contents start with "(" and end with ")"
		boolean begin = false;
		String xx = "";
		for (int i = 0; i < comment.length(); i++) {
			char x = comment.charAt(i);
			if(x == '('){
				begin = true;
				continue;
			}
			if(x == ')'){
				begin = false;
				if(!StringUtils.isBlank(xx)){
					flags.add(xx);
				}
				xx = "";
			}
			if(begin){
				xx += x;
			}
		}
		return flags;
	}
	

	protected String escapeComment(String comment) {
		String result = "";
		comment = StringUtils.trim(StringUtils.defaultString(comment));
		comment = comment.replaceAll("\\s", " ");
		result = StringUtils.escapeAssicXml(comment);
		return result;
	}
}
